﻿using System.Collections.Generic;
using System.Globalization;
using Halk.Builder;
using Halk.Dao;
using Halk.Model;

namespace Halk.Mover
{
    public class NovelMover
    {
        private ArticleInfo _articleTarget = new ArticleInfo();

        private IList<ArticleInfo> _articleListSource = new List<ArticleInfo>();

        private IList<ChapterInfo> _chapterListTarget = new List<ChapterInfo>();

        private IList<ChapterInfo> _chapterListSource = new List<ChapterInfo>();
 
/*
        private readonly IList<AttachInfo> _attachListTarget=new List<AttachInfo>();
*/

/*
        private IList<AttachInfo> _attachListSource = new List<AttachInfo>();
*/

        private readonly Dictionary<string, DaoArticle> _mapsArticleDao = new Dictionary<string, DaoArticle>();

        private readonly Dictionary<string, DaoChapter> _mapsChapterDao = new Dictionary<string, DaoChapter>();

        private readonly Dictionary<string, DaoAttachs> _mapsAttachDao = new Dictionary<string, DaoAttachs>(); 
 
        private readonly OpfBuilder _opfBuilder=new OpfBuilder();

        private readonly Dictionary<string, int> _mapsArticleId = new Dictionary<string, int>();

        private readonly Dictionary<string, int> _mapsChapterId = new Dictionary<string, int>();

        private readonly Dictionary<string, int> _mapsAttachId = new Dictionary<string, int>();

        private readonly Dictionary<string,HtmlBuilder> _mapsHtmlBuilder=new Dictionary<string, HtmlBuilder>(); 

        private string _flagTarget;

        private string _flagSource;

        private int _repeatTimes;

        private int _articleIndex;

        private int _lastTargetChapterCount;

        private void Initialize()
        {
            string targtet, source;
            for (var i = 0; i < Config.ConfigManage.Instace().GetSize(); ++i)
            {
                targtet = Config.ConfigManage.Instace().GetConfig().flag + "target";
                source = Config.ConfigManage.Instace().GetConfig().flag + "source";
                #region target
                if (!_mapsArticleDao.ContainsKey(targtet))
                {
                    var targetDaoArticle = new DaoArticle(Config.ConfigManage.Instace().GetConfig().ConnString);
                    _mapsArticleDao[targtet] = targetDaoArticle;
                    _mapsArticleId[targtet] = targetDaoArticle.GetArticleMaxId();
                }
                if (!_mapsChapterDao.ContainsKey(targtet))
                {
                    var dao = new DaoChapter(Config.ConfigManage.Instace().GetConfig().ConnString);
                    _mapsChapterDao[targtet] = dao;
                    _mapsChapterId[targtet] = dao.GetChapterMaxId();
                }
                if (!_mapsAttachDao.ContainsKey(targtet))
                {
                    var dao = new DaoAttachs(Config.ConfigManage.Instace().GetConfig().ConnString);
                    _mapsAttachDao [targtet] = dao;
                    _mapsAttachId[targtet] = dao.GetAttachMaxID();
                }
                #endregion

                #region source
                if (!_mapsArticleDao.ContainsKey(source))
                {
                    var sourceDaoArticle = new DaoArticle(Config.ConfigManage.Instace().GetConfig().ConnString);
                    _mapsArticleDao[source] = sourceDaoArticle;
                }
                if(!_mapsChapterDao.ContainsKey(source))
                {
                    var dao = new DaoChapter(Config.ConfigManage.Instace().GetConfig().ConnString);
                    _mapsChapterDao[source] = dao;
                }
                if(!_mapsAttachDao.ContainsKey(source))
                {
                    var dao = new DaoAttachs(Config.ConfigManage.Instace().GetConfig().ConnString);
                    _mapsAttachDao[source] = dao;
                }
                if (!_mapsHtmlBuilder.ContainsKey(Config.ConfigManage.Instace().GetConfig().flag))
                {
                    var htmlBuilder = new HtmlBuilder(Config.ConfigManage.Instace().GetConfig());
                    _mapsHtmlBuilder[Config.ConfigManage.Instace().GetConfig().flag] = htmlBuilder;
                }
                #endregion
                Config.ConfigManage.Instace().MoveNext();
            }
        }

        private void AnalysePages(int flag, int posBegin)
        {
            switch (flag)
            {
                case 1://查找上一章节
                    {
                        for (var i = posBegin-1; i >=0; i--)
                        {
                            if (_chapterListTarget[i].chaptertype != 0) continue;
                            _chapterListTarget[posBegin].previewpage = _chapterListTarget[i].chapterid;
                            return;
                        }
                    }
                    break;
                case 2://查找下一章节
                    {
                        for (var i = posBegin+1; i < _chapterListTarget.Count; i++)
                        {
                            if (_chapterListTarget[i].chaptertype != 0) continue;
                            _chapterListTarget[posBegin].nextpage = _chapterListTarget[i].chapterid;
                            return;
                        }
                    }
                    break;
            }
        }

        public void Working()
        {
            Initialize();
            Config.ConfigManage.Instace().MoveFirst();
            for (var i = 0; i < Config.ConfigManage.Instace().GetSize(); i++)
            {
                _flagSource = Config.ConfigManage.Instace().GetConfig().flag + "source";
                _flagTarget = Config.ConfigManage.Instace().GetConfig().flag + "target";
                GetNovelList();
                Config.ConfigManage.Instace().MoveNext();
            }
        }

        private void GetNovelList()
        {
            _articleListSource =
                _mapsArticleDao[_flagSource].GetListByUpdateTime(Config.ConfigManage.Instace().GetConfig().LastUpdate);
            if (_articleListSource.Count == 0)
            {
                System.Threading.Thread.Sleep(Config.ConfigManage.Instace().GetConfig().SleepTimes);
                return;
            }
            _repeatTimes = 0; //重复次数置零
            for (_articleIndex = 0;
                 _articleIndex < _articleListSource.Count &&
                 _repeatTimes < Config.ConfigManage.Instace().GetConfig().RepeatMax &&
                 Config.SystemManage.Instace().GetOnOff();
                 _articleIndex++)
            {
                if (!GetNovel()) continue;
                GetChapterList();
                CompleteNovel();
            }
            Config.ConfigManage.Instace().Save();
        }

        private bool GetNovel()
        {
            _articleTarget = _mapsArticleDao[_flagTarget].GetByName(_articleListSource[_articleIndex].articlename);
            var exists = _articleTarget.articleid == 0;
            if(!exists)
            {
                _articleTarget = _articleListSource[_articleIndex];
                _articleTarget.lastchapter = "";
                _articleTarget.lastchapterid = 0;
                _articleTarget.lastvolume = "";
                _articleTarget.lastvolumeid = 0;
            }
            _opfBuilder.AddMetadata(_articleTarget);
            _chapterListSource = _mapsChapterDao[_flagSource].GetList(_articleListSource[_articleIndex].articleid);
            if (exists)
            {
                _chapterListTarget = _mapsChapterDao[_flagTarget].GetList(_articleTarget.articleid);
                _lastTargetChapterCount = _chapterListTarget.Count;
                if (_chapterListSource.Count == _chapterListTarget.Count)
                {
                    _repeatTimes++;
                    Config.ConfigManage.Instace().GetConfig().LastUpdate = _articleListSource[_articleIndex].lastupdate.ToString(CultureInfo.InvariantCulture);
                    return false;
                }
            }
            else
            {
                _articleTarget.downloadlink = string.Format("{0}/files/article/txtfull/{1}/{2}.txt",
                                                            Config.ConfigManage.Instace().GetConfig().TargetDomain,
                                                            _articleListSource[_articleIndex].articleid/1000,
                                                            _articleListSource[_articleIndex].articleid);
            }
            return true;
        }

        private void GetChapterList()
        {
            for (var ci = 0; ci < _chapterListSource.Count; ci++)
            {
                if (_chapterListSource.Count > ci)
                {_opfBuilder.AddMainfestAndSpine(_chapterListTarget[ci]);}
                else
                {
                    _chapterListTarget[ci] = _chapterListSource[ci];
                    _chapterListTarget[ci].articleid = _articleTarget.articleid;
                    _chapterListTarget[ci].chapterid = _mapsChapterId[_flagTarget];
                    _chapterListTarget[ci].isnew = 1;
                    _mapsChapterDao[_flagTarget].Add(_chapterListTarget[ci]);
                    _mapsChapterId[_flagTarget]++;
                }
            }
        }

/*
        private void GetAttachs(ChapterInfo sourceChapter,ChapterInfo targetChapter)
        {
            _attachListSource = _mapsAttachDao[_flagSource].GetAttachs(sourceChapter);
            for (var i = 0; i < _attachListSource.Count; i++)
            {
                _attachListTarget[i].articleid = targetChapter.articleid;
                _attachListTarget[i].chapterid = targetChapter.chapterid;
                _attachListTarget[i].attachid = _mapsAttachId[_flagTarget];
                _attachListTarget[i].name = _attachListSource[i].name;
                _attachListTarget[i].cclass = _attachListSource[i].cclass;
                _attachListTarget[i].postfix = _attachListSource[i].postfix;
                _attachListTarget[i].size = _attachListSource[i].size;
                _attachListTarget[i].hits = _attachListSource[i].hits;
                _attachListTarget[i].needexp = _attachListSource[i].needexp;
                _attachListTarget[i].uptime = _attachListSource[i].uptime;
                _mapsAttachDao[_flagSource].Add(_attachListTarget[i]);
            }
        }
*/

        private void CompleteNovel()
        {
            if (!_opfBuilder.ConfirmOptFile(Config.ConfigManage.Instace().GetConfig().FilePath, _articleTarget.articleid))
                return;
            for (var ci = _lastTargetChapterCount; ci < _chapterListSource.Count; ci++)
            {
                if(ci==0)
                {
                    AnalysePages(2,ci);
                }
                else if(ci>0 && ci<_chapterListTarget.Count-1)
                {
                    AnalysePages(1,ci);//有后一章节，且有前一章节
                    AnalysePages(2,ci);
                }
                else if (ci == _chapterListTarget.Count - 1)
                {
                    AnalysePages(1, ci); //有前一章节
                }
                _mapsHtmlBuilder[_flagTarget].CreateChapterHtml(_articleTarget, _chapterListTarget[ci]);
                System.Threading.Thread.Sleep(Config.ConfigManage.Instace().GetConfig().SleepChapter);
            }
            _mapsHtmlBuilder[_flagTarget].CreateIndexHtml(_articleTarget, _chapterListTarget);
            Config.ConfigManage.Instace().GetConfig().LastUpdate = _articleListSource[_articleIndex].lastupdate.ToString(CultureInfo.InvariantCulture);
        }
    }
}
